using System;
using System.Collections.Generic;
using System.Text;
using Zsa.Emulation.Memory;
using System.IO;
using Zsa.Emulation.Cartridge;

namespace Zsa.Emulation.PPU
{

    /// <summary>
    /// The ppu memories main class.
    /// </summary>
    public class PpuMemoryManager : MemoryMap
    {
        #region Fields

        /// <summary>
        /// The cartridge io.
        /// </summary>
        private Cartridge.CartridgeSlot _CartIO;

        


        #region Memory
        /// <summary>
        /// The first name and attribute table.
        /// </summary>
        private NameAttributeTable _TableOne;

        /// <summary>
        /// The second name and attribute table
        /// </summary>
        private NameAttributeTable _TableTwo;


        /// <summary>
        /// The color palette.
        /// </summary>
        private PaletteTable _BackgroundColorPalette;

        /// <summary>
        /// The sprite background palette.
        /// </summary>
        private PaletteTable _SpriteColorPalette;
        #endregion Memory


        #endregion Fields

        #region Constructor
        /// <summary>
        /// Initializes a new instance of the <see cref="T:PpuMemoryManager"/> class.
        /// </summary>
        /// <param name="cartIO">The cart IO.</param>
        public PpuMemoryManager(Cartridge.CartridgeSlot cartIO)
        {
            _CartIO = cartIO;
        }
        #endregion Constructor

        #region Methods


        /// <summary>
        /// Resets the memory.
        /// </summary>
        /// <returns></returns>
        protected override MemoryItem[] OnInit()
        {
            _BackgroundColorPalette = new PaletteTable(ColorPaletteType.Background, ColorPaletteSettings.CreateDefault());
            _SpriteColorPalette = new PaletteTable(ColorPaletteType.Sprite, ColorPaletteSettings.CreateDefault());
            _TableOne = new NameAttributeTable();
            _TableTwo = new NameAttributeTable();

            MemoryItem[] _MemItems = new MemoryItem[]
            {
                // The first pattern table.
                new MemoryItem(
                    _CartIO.VideoMemoryBankOne.Memory,
                    _CartIO.VideoMemoryBankOne.Blocks
                ),
                // The second pattern table.
                new MemoryItem(
                    _CartIO.VideoMemoryBankTwo.Memory,
                    _CartIO.VideoMemoryBankTwo.Blocks
                ),
                // The first and third pattern tables.
                new MemoryItem(
                    _TableOne,
                    new MemoryBlock(
                        VideoMemoryConstants.NameTableOneStart,
                        VideoMemoryConstants.NameAttributeTableSize
                    ),
                    new MemoryBlock(
                        VideoMemoryConstants.NameTableThreeStart,
                        VideoMemoryConstants.NameAttributeTableSize
                    ),
                    new MemoryBlock(
                        0x3000,
                        VideoMemoryConstants.NameTableSize
                    ),
                    new MemoryBlock(
                        0x3780,
                        VideoMemoryConstants.NameTableSize
                    )
                ),
                // The second and fourth pattern tables.
                new MemoryItem(
                    _TableTwo,
                    new MemoryBlock(
                        VideoMemoryConstants.NameTableTwoStart,
                        VideoMemoryConstants.NameAttributeTableSize
                    ),
                    new MemoryBlock(
                        VideoMemoryConstants.NameTableFourStart,
                        VideoMemoryConstants.NameAttributeTableSize
                    ),
                    new MemoryBlock(
                        0x33C0,
                        VideoMemoryConstants.NameTableSize
                    ),
                    new MemoryBlock(
                        0x3B40,
                        VideoMemoryConstants.NameTableSize
                    )
                ),
                //new MemoryItem(
                //    _TableOne,
                //    new MemoryBlock(
                    
                //    )
                new MemoryItem(
                    _BackgroundColorPalette,
                    new MemoryBlock(
                        VideoMemoryConstants.ImagePaletteStart,
                        16
                    ),
                    new MemoryBlock(
                        0x3F20,
                        16
                    ),
                     new MemoryBlock(
                        0x3F40,
                        16
                    ),
                    new MemoryBlock(
                        0x3F60,
                        16
                    ),
                    new MemoryBlock(
                        0x3F80,
                        16
                    ),
                    new MemoryBlock(
                        0x3FA0,
                        16
                    ),
                    new MemoryBlock(
                        0x3FC0,
                        16
                    ),
                    new MemoryBlock(
                        0x3FE0,
                        16
                    )
                ),
                new MemoryItem(
                    _SpriteColorPalette,
                    new MemoryBlock(
                        VideoMemoryConstants.SpritePaletteStart,
                        16
                    ),
                    new MemoryBlock(
                        0x3F30,
                        16
                    ),
                    new MemoryBlock(
                        0x3F50,
                        16
                    ),
                    new MemoryBlock(
                        0x3F70,
                        16
                    ),
                    new MemoryBlock(
                        0x3F90,
                        16
                    ),
                    new MemoryBlock(
                        0x3FB0,
                        16
                    ),
                    new MemoryBlock(
                        0x3FD0,
                        16
                    ),
                    new MemoryBlock(
                        0x3FF0,
                        16
                    )
                )
            };

            return _MemItems;

            
        }


        public override void Write(int address, byte data)
        {

            if (address >= 0xC000)
            {
                address -= 0xC000;
            }
            else if (address >= 0x8000)
            {
                address -= 0x8000;

            }
            else if (address >= 0x4000)
            {
                address -= 0x4000;
            }

            base.Write(address, data);
        }


        
        


        ///// <summary>
        ///// Resets the memory.
        ///// </summary>
        ///// <returns></returns>
        //protected override IMemory[] OnInit()
        //{
        //    _PatternTables = ReadPatternTables(_CartIO);

            
        //    _PatternTableOne = _PatternTables[0];
        //    _PatternTableTwo = _PatternTables[1];

        //    // Create the memory.
        //    _MemoryStream = new MemoryStream(new byte[4096], true);

        //    // Create the first name table.
        //    _TableOne = new NameAttributeTable(
        //        0x2000,
        //        0,
        //        _MemoryStream
        //    );
            
            
        //    // Create the attribute table.
        //    _TableTwo = new NameAttributeTable(
        //        0x2400,
        //        0x400,
        //        _MemoryStream
        //    );

        //    // Create the second name table.
        //    _TableThree = new NameAttributeTable(
        //        0x2800,
        //        0,
        //        _MemoryStream
        //        );
        //    // Create the second attribute table.
        //    _TableFour = new NameAttributeTable(
        //        0x2C00,
        //        0x400,
        //        _MemoryStream
        //    );

        //    // Mirror 
        //    _TableMirror = new MemoryBank(
        //        0xF00,
        //        0x3000,
        //        _MemoryStream,
        //        0,
        //        false
        //    );

        //    // The two color palettes.
        //    _ColorPalette = new MemoryBank(
        //        32,
        //        0x3F00,
        //        _MemoryStream,
        //        2048,
        //        false
        //    );


        //    _ColorPaletteMirror = new MemoryBank(
        //        32,
        //        0x3F20,
        //        _MemoryStream,
        //        2048,
        //        false
        //    );


        //    return new IMemory[]
        //    {
        //        _PatternTableOne,
        //        _PatternTableTwo,
        //        _TableOne,
        //        _TableTwo,
        //        _TableThree,
        //        _TableFour,
        //        _TableMirror,


        //    };
        //}







        #endregion Methods

        #region Properties
        /// <summary>
        /// Gets the pattern table one.
        /// </summary>
        /// <value>The pattern table one.</value>
        public PatternTable PatternTableOne
        {
            get { return _CartIO.VideoMemoryBankOne.Memory as PatternTable; }
        }
        /// <summary>
        /// Gets the pattern table two.
        /// </summary>
        /// <value>The pattern table two.</value>
        public PatternTable PatternTableTwo
        {
            get { return _CartIO.VideoMemoryBankTwo.Memory as PatternTable; }
        }

        /// <summary>
        /// Gets the name attribute table one.
        /// </summary>
        /// <value>The name attribute table one.</value>
        public NameAttributeTable NameAttributeTableOne
        {
            get
            {
                return _TableOne;
            }
        }

        /// <summary>
        /// Gets the name attribute table two.
        /// </summary>
        /// <value>The name attribute table two.</value>
        public NameAttributeTable NameAttributeTableTwo
        {
            get
            {
                return _TableTwo;
            }
        }


        public PaletteTable BackgroundColorPalette
        {
            get {
                return _BackgroundColorPalette;
            }
        }


        public PaletteTable SpriteColorPalette
        {
            get
            {
                return _SpriteColorPalette;
            }
        }
        #endregion Properties


    }
}
